from io import BytesIO
from itertools import islice
from typing import Any

import oss2
import requests

from src.config.conf import cfg
from src.utils.common import generate_random_string


class Oss:
    def __init__(self) -> None:
        self.auth = oss2.Auth(cfg.oss.access_key, cfg.oss.secret_key)
        self.endpoint = cfg.oss.end_point
        self.bucket = oss2.Bucket(self.auth, self.endpoint, bucket_name=cfg.oss.bucket_name)

    def get_bucket_list(self):
        """列举当前endpoint下所有的bucket_name"""
        service = oss2.Service(self.auth, self.endpoint)
        bucket_list = [b.name for b in oss2.BucketIterator(service)]
        return bucket_list

    def get_all_file(self, prefix):
        """获取指定前缀下所有文件"""
        for b in islice(oss2.ObjectIterator(self.bucket, prefix=prefix), 10):
            yield b.key

    def read_file(self, path):
        try:
            file_info = self.bucket.get_object(path).read()
            return file_info
        except Exception as e:
            print(e, '文件不存在')

    def exists_file(self, path):
        try:
            return self.bucket.object_exists(path)
        except Exception as e:
            print(e, '文件不存在')
            return False

    def download_file(self, path, save_path):
        try:
            self.bucket.get_object_to_file(path, save_path)
        except Exception as e:
            print(e, '下载失败')
            return None

        return save_path

    def upload_file(self, ext, local_path, file_name=None):
        if not file_name:
            file_name = f'{cfg.oss.file_dir}{generate_random_string(32)}{ext}'
        result = self.bucket.put_object_from_file(file_name, local_path)
        if result.status == 200:
            return f'https://{cfg.oss.bucket_name}.{self.endpoint}/{file_name}'
        return None

    def upload_all_file(self, ext: str, data: Any):
        file_name = f'{cfg.oss.file_dir}{generate_random_string(32)}{ext}'
        result = self.bucket.put_object(file_name, data)
        return f'https://{cfg.oss.bucket_name}.{self.endpoint}/{file_name}'

    def upload_remote_file(self, file_url: str, ext: str, file_name = None):
        if not file_name:
            file_name = f'{cfg.oss.file_dir}{generate_random_string(32)}{ext}'
        response = requests.get(file_url, stream=True)
        self.bucket.put_object(file_name, response.content)
        return f'https://{cfg.oss.bucket_name}.{self.endpoint}/{file_name}'

    def upload_from_stream(self, ext: str, stream: BytesIO, file_name = None):
        if not file_name:
            file_name = f'{cfg.oss.file_dir}{generate_random_string(32)}{ext}'
        self.bucket.put_object(file_name, stream)
        return f'https://{cfg.oss.bucket_name}.{self.endpoint}/{file_name}'
